package demoMod.nanaki.stances;

import basemod.ReflectionHacks;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.megacrit.cardcrawl.actions.AbstractGameAction;
import com.megacrit.cardcrawl.actions.common.GainEnergyAction;
import com.megacrit.cardcrawl.actions.watcher.ChangeStanceAction;
import com.megacrit.cardcrawl.audio.SoundInfo;
import com.megacrit.cardcrawl.audio.SoundMaster;
import com.megacrit.cardcrawl.cards.AbstractCard;
import com.megacrit.cardcrawl.cards.DamageInfo;
import com.megacrit.cardcrawl.core.CardCrawlGame;
import com.megacrit.cardcrawl.core.Settings;
import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
import com.megacrit.cardcrawl.localization.StanceStrings;
import com.megacrit.cardcrawl.powers.AbstractPower;
import com.megacrit.cardcrawl.relics.AbstractRelic;
import com.megacrit.cardcrawl.vfx.BorderFlashEffect;
import demoMod.anm2player.AnimatedActor;
import demoMod.nanaki.NanakiMod;
import demoMod.nanaki.audio.MySoundInfo;
import demoMod.nanaki.interfaces.EndOfTurnHook;
import demoMod.nanaki.interfaces.ExitStropheHook;
import demoMod.nanaki.patches.GameActionManagerPatch;
import demoMod.nanaki.utils.GetWaitAction;
import demoMod.nanaki.vfx.StropheCircleEffect;
import demoMod.nanaki.vfx.StropheParticleEffect;

import java.util.ArrayList;
import java.util.stream.Collectors;

public class Strophe2 extends AbstractStrophe {
    public static final String STANCE_ID = "Nanaki:Strophe2";

    private static final StanceStrings stanceString = CardCrawlGame.languagePack.getStanceString(STANCE_ID);

    private static long sfxId = -1L;
    private static long introId = -1L;
    private StropheCircleEffect circleEffect;

    public Strophe2() {
        this.ID = STANCE_ID;
        this.name = stanceString.NAME;
        updateDescription();
    }

    public void updateDescription() {
        this.description = stanceString.DESCRIPTION[0];
    }

    public void updateAnimation() {
        if (!Settings.DISABLE_EFFECTS) {
            this.particleTimer2 -= Gdx.graphics.getDeltaTime();

            if (this.particleTimer2 < 0.0F) {
                this.particleTimer2 = 0.11F;
                AbstractDungeon.effectsQueue.add(new StropheParticleEffect(AbstractDungeon.player.hb.cX - AbstractDungeon.player.hb.width / 2.0F, AbstractDungeon.player.hb.cY - AbstractDungeon.player.hb.height / 2.0F - 48.0F * Settings.scale, StropheParticleEffect.ParticleType.FOVER));
            }
        }
    }

    public float atDamageGive(float damage, DamageInfo.DamageType type) {
        if (type == DamageInfo.DamageType.NORMAL)
            return damage * 1.1F;
        return damage;
    }

    private AbstractGameAction playIntroSfxAction;
    private AbstractGameAction playLoopSfxAction;

    public void onEnterStance() {
        if (sfxId != -1L) stopIdleSfx();
        NanakiMod.addToBot(GetWaitAction.doAndWait(() -> CardCrawlGame.sound.play("STROPHE_2_ENTER"), 2.474F));
        playIntroSfxAction = GetWaitAction.doAndWait(() -> introId = CardCrawlGame.sound.play("STROPHE_2_INTRO"), 9.897F);
        NanakiMod.addToBot(playIntroSfxAction);
        playLoopSfxAction = new AbstractGameAction() {
            @Override
            public void update() {
                sfxId = CardCrawlGame.sound.playAndLoop("STROPHE_2_LOOP");
                isDone = true;
            }
        };
        NanakiMod.addToBot(playLoopSfxAction);
        AbstractDungeon.effectsQueue.add(new BorderFlashEffect(Color.TEAL, true));
        AnimatedActor actor = new AnimatedActor(NanakiMod.getResourcePath("stances/strophe2.anm2"));
        actor.scale = 2.68F * 0.85F;
        actor.xPosition = AbstractDungeon.player.drawX;
        actor.yPosition = AbstractDungeon.player.drawY;
        actor.rotation = -30.0F;
        actor.addTriggerEvent("0", animation -> actor.setCurAnimation("loop"));
        actor.addTriggerEvent("1", animation -> NanakiMod.addToParallelBot(GetWaitAction.doAndWait(() -> {
            vfxList.remove(actor);
            actor.dispose();
        }, 0.0F)));
        actor.flipX = true;
        actor.setCurAnimation("intro");
        vfxList.add(actor);
        circleEffect = new StropheCircleEffect(getStropheLevel());
        AbstractDungeon.effectsQueue.add(circleEffect);
    }

    @Override
    public void onEndOfTurn() {
        for (AbstractCard card : AbstractDungeon.player.drawPile.group.stream().filter(c -> c instanceof EndOfTurnHook).collect(Collectors.toList())) {
            ((EndOfTurnHook) card).onEndOfTurn();
        }
        for (AbstractCard card : AbstractDungeon.player.hand.group.stream().filter(c -> c instanceof EndOfTurnHook).collect(Collectors.toList())) {
            ((EndOfTurnHook) card).onEndOfTurn();
        }
        for (AbstractCard card : AbstractDungeon.player.discardPile.group.stream().filter(c -> c instanceof EndOfTurnHook).collect(Collectors.toList())) {
            ((EndOfTurnHook) card).onEndOfTurn();
        }
        GameActionManagerPatch.StropheExitedThisTurn = 0;
    }

    public void onExitStance() {
        GameActionManagerPatch.StropheExitedThisTurn++;
        for (AbstractCard card : AbstractDungeon.player.drawPile.group.stream().filter(c -> c instanceof ExitStropheHook).collect(Collectors.toList())) {
            ((ExitStropheHook) card).onExitStrophe();
        }
        for (AbstractCard card : AbstractDungeon.player.hand.group.stream().filter(c -> c instanceof ExitStropheHook).collect(Collectors.toList())) {
            ((ExitStropheHook) card).onExitStrophe();
        }
        for (AbstractCard card : AbstractDungeon.player.discardPile.group.stream().filter(c -> c instanceof ExitStropheHook).collect(Collectors.toList())) {
            ((ExitStropheHook) card).onExitStrophe();
        }
        for (AbstractPower power : AbstractDungeon.player.powers.stream().filter(p -> p instanceof ExitStropheHook).collect(Collectors.toList())) {
            ((ExitStropheHook) power).onExitStrophe();
        }
        for (AbstractRelic relic : AbstractDungeon.player.relics.stream().filter(p -> p instanceof ExitStropheHook).collect(Collectors.toList())) {
            ((ExitStropheHook) relic).onExitStrophe();
        }
        AbstractDungeon.actionManager.addToBottom(new GainEnergyAction(3));
        stopIdleSfx();
        circleEffect.dismiss();
    }

    public void atStartOfTurn() {
        AbstractDungeon.actionManager.addToBottom(new ChangeStanceAction(getNextStrophe()));
    }

    public void stopIdleSfx() {
        if (playLoopSfxAction != null) {
            if (sfxId != -1L) {
                ArrayList<SoundInfo> fadeOutList = ReflectionHacks.getPrivate(CardCrawlGame.sound, SoundMaster.class, "fadeOutList");
                fadeOutList.add(new MySoundInfo("STROPHE_2_LOOP", sfxId));
                sfxId = -1L;
            }
            NanakiMod.cancelAction(playLoopSfxAction);
        }
        if (playIntroSfxAction != null) {
            if (introId != -1L) {
                ArrayList<SoundInfo> fadeOutList = ReflectionHacks.getPrivate(CardCrawlGame.sound, SoundMaster.class, "fadeOutList");
                fadeOutList.add(new MySoundInfo("STROPHE_2_INTRO", introId));
                introId = -1L;
            }
            NanakiMod.cancelAction(playIntroSfxAction);
        }
    }

    @Override
    public int getStropheLevel() {
        return 2;
    }

    @Override
    public AbstractStrophe getNextStrophe() {
        return new Strophe3();
    }
}
